/*
 * magiced_buffer.hpp
 *
 *  Created on: 2023年9月5日
 *      Author: Dylan.Gao
 */

#ifndef _DM_MAGICED_BUFFER_HPP_
#define _DM_MAGICED_BUFFER_HPP_

#include <dm/magic.hpp>
#include <dm/bits.hpp>

namespace dm{

/**
 * 具备魔数管理的缓冲区
 * @tparam TRecord 记录类型
 * @tparam SizeOfMask 记录占用掩码字节数.记录个数x8
 */
template<typename TRecord,int SizeOfMask=4>
struct TSMagicedBuffer{
	typedef CMagic::magic_t magic_t;

	magic_t magic;				//!< 魔数。代表了本缓冲区的状态
	uint8 masks[SizeOfMask];		//!< 缓冲区使用情况
	TRecord data[SizeOfMask*8];	//!< 数据区

	void init();

	/**
	 * 获取缓冲区大小
	 * @return
	 */
	inline static int size(){
		return SizeOfMask * 8;
	}

	/**
	 * 获取当前已标记的记录数量
	 * @return
	 */
	int count()const;

	/**
	 * 是否无标记的记录
	 * @return
	 */
	inline bool ifNoneMasked()const{
		return count()==0;
	}

	/**
	 * 是否记录都已经标记
	 * @return
	 */
	inline bool ifAllMasked()const{
		return count()==size();
	}

	/**
	 * 标记所有记录
	 */
	void maskAll();

	/**
	 * 去除所有标记
	 */
	void maskNone();

	/**
	 * 记录index是否被标记
	 * @param index
	 * @return
	 */
	inline bool ifMasked( int index )const{
		return bits_get(index, masks);
	}

	/**
	 * 标记记录index。
	 * @param index
	 * @return:是否标记成功
	 * - true：标记成功
	 * - false: 标记未成功，因为已经标记过
	 */
	bool mask( int index );

	/**
	 * 取消标记记录index
	 * @param index
	 * @return 取消标记是否成功
	 * - true: 取消标记成功
	 * - false: 取消标记失败，因为记录未被标记
	 */
	bool unmask( int index );

	/**
	 * 查找下一个被标记的索引
	 * @param p 起始索引（包含）
	 * @return
	 * - <0: 错误
	 * - size():未找到
	 */
	int nextMasked( int p=0 )const;

	/**
	 * 查找上一个被标记的索引
	 * @param p 起始索引号(包含），-1全部
	 * @return
	 * - <0: 错误
	 * - size(): 未找到
	 */
	int lastMasked( int p=-1 )const;

	/**
	 * 查找下一个未标记的索引
	 * @param p 起始索引（包含）
	 * @return
	 * - <0: 错误
	 * - size(): 未找到
	 */
	int nextUnmask( int p=0 )const;

	/**
	 * 查找上一个未标记的索引
	 * @param p 起始索引号（包含），-1全部
	 * @return
	 * - <0: 错误
	 * - size(): 未找到
	 */
	int lastUnmask( int p=-1 )const;
};

/**
 * 初始化结构体
 * @tparam TRecord
 * @tparam SizeOfMask
 */
template<typename TRecord,int SizeOfMask>
void TSMagicedBuffer<TRecord,SizeOfMask>::init(){
	CMagic m(&magic);
	m.refresh();	// 这里使用了随机数作为初始化

	for( int i=0;i<SizeOfMask;++i )
		masks[i] = 0;
}

/**
 * 获取当前记录数
 * @tparam TRecord
 * @tparam SizeOfMask
 * @return
 */
template<typename TRecord,int SizeOfMask>
int TSMagicedBuffer<TRecord,SizeOfMask>::count()const{
	int sum = 0;
	for( int i=0;i<SizeOfMask;++i ){
		if( masks[i]==0xFF )
			sum += 8;
		else if( masks[i]!=0 ){
			for( int j=0;j<8;++j )
				if( bit_get(masks[i], j) )
					++sum;
		}
	}

	return sum;
}

template<typename TRecord,int SizeOfMask>
void TSMagicedBuffer<TRecord,SizeOfMask>::maskAll(){
	for( int i=0;i<SizeOfMask;++i ){
		if( masks[i]!=0xFF ){
			masks[i] = 0xFF;
			CMagic m(&magic);
			m.refresh();
		}
	}
}

template<typename TRecord,int SizeOfMask>
void TSMagicedBuffer<TRecord,SizeOfMask>::maskNone(){
	for( int i=0;i<SizeOfMask;++i ){
		if( masks[i]!=0x00 ){
			masks[i] = 0x00;
			CMagic m(&magic);
			m.refresh();
		}
	}
}

template<typename TRecord,int SizeOfMask>
bool TSMagicedBuffer<TRecord,SizeOfMask>::mask( int index ){
	if( bits_get(index, masks) )
		return false;
	bits_set(index, masks);
	CMagic m(&magic);
	m.refresh();
	return true;
}

template<typename TRecord,int SizeOfMask>
bool TSMagicedBuffer<TRecord,SizeOfMask>::unmask( int index ){
	if( bits_get(index, masks) ){
		bits_clear(index, masks);
		CMagic m(&magic);
		m.refresh();
		return true;
	}else
		return false;

}

template<typename TRecord,int SizeOfMask>
int TSMagicedBuffer<TRecord,SizeOfMask>::nextMasked( int p )const{
	if( p<0 || p>=size() )
		return -1;	// 参数错误

	for( ;p<=size();++p ){
		if( bits_get(p, masks) )
			return p;
	}

	return size();	// 没有记录
}

template<typename TRecord,int SizeOfMask>
int TSMagicedBuffer<TRecord,SizeOfMask>::lastMasked( int p )const{
	if( p==-1 )
		p = size()-1;

	if( p<0 || p>=size() )
		return -1;	// 参数错误

	for( ;p>=0;--p ){
		if( bits_get(p, masks) )
			return p;
	}

	return size();	// 没有记录
}

template<typename TRecord,int SizeOfMask>
int TSMagicedBuffer<TRecord,SizeOfMask>::nextUnmask( int p )const{
	if( p<0 || p>=size() )
		return -1;	// 参数错误

	for( ;p<=size();++p ){
		if( !bits_get(p, masks) )
			return p;
	}

	return size();	// 没有记录
}

template<typename TRecord,int SizeOfMask>
int TSMagicedBuffer<TRecord,SizeOfMask>::lastUnmask( int p )const{
	if( p==-1 )
		p = size()-1;

	if( p<0 || p>=size() )
		return -1;	// 参数错误

	for( ;p>=0;--p ){
		if( !bits_get(p, masks) )
			return p;
	}

	return size();	// 没有记录
}

}

#endif /* _DM_MAGICED_BUFFER_HPP_ */
